#!/usr/bin/env python
#^#
# Python Oracle VM Server Management
#
# Copyright (C) 2011 ovm Project
# Author: Choonho Son <choonho@kt.com>
# URL: <http://ovm.googlecode.com>
# For license information, see LICENSE.TXT
#


__author__    = "Choonho son"
__copyright__ = "Copyrought 2011, OVM Project"
__license__   = "BSD"
__version__   = "1.0"
__maintainer__ = "Choonho Son"
__email__     = "choonho@kt.com"
__status__    = "Stable"

from utils.Command import *
from utils.ipaddr import *

import sys
import socket
import traceback
from sets import Set
from optparse import OptionParser
from ConfigParser import ConfigParser
import urllib
from os.path import exists

command = Command()

def getPartitions():
    """
    @return : partition list
    find current partitions in /proc/partitions
    """
    fp = open("/proc/partitions")
    partitions = []
    for line in fp:
        part = re.findall(r'(\w+)', line)
        if len(part) != 4: continue
        if part[3] != "name":
            partitions.append(part[3])

    return Set(partitions)

                                  
class iSCSI:
    def __init__(self,portal):
        self.portal = portal
        self.command = Command()
        self.iqns = []
        self.old_parts = getPartitions()
        self.new_parts = Set()
        self.login_iqn = None
        self.mount_dsk = None

    def session(self):
        """
        @return : current iSCSI seesion
        """
        cmd = "iscsiadm -m session"
        try:
            rcode = self.command.execute(cmd)
            if len(rcode[1]) > 0: raise CmdError(rcode[1])
            return rcode[0]
        
        except CmdError, e:
            print e
            # may be -> no active sessions.
            return rcode[1]
            
        except:
            print "#### Unknown Error ####"
            print traceback.print_exc()
            sys.exit()
                                                                                                                                                                                                        
    def discovery(self):
        """
        @return : IQNs
        find iSCSI IQNs
        """
        cmd = "iscsiadm -m discovery -t sendtargets -p %s" % self.portal
        try:
            rcode = self.command.execute(cmd)
            if len(rcode[1]) > 0: raise CmdError(rcode[1])

            #result look like
            #10.1.1.250:3260,2 iqn.1986-03.com.sun:02:309267fe-7244-c8f6-fa06-a189b0bfb4a7
            for line in rcode[0].split("\n"):
                items = line.split(" ")
                if len(items) == 2:
                    portal = (items[0].split(","))[0]
                    iqn = items[1]
                    self.iqns.append( (portal,iqn) )

            return True
        
        except CmdError, e:
            print e
            return False

        except:
            print "#### Unknown Error ####"
            print traceback.print_exc()
            return False
        

    def login(self,target,portal,method="login"):
        """
        @param target : iqn
        @return :True if Success
        iscsi login with target iqn
        """

        self.login_iqn = target
        cmd = "iscsiadm --mode node --target %s --portal %s --%s" % (target, portal,method)
        
        try:
            rcode = self.command.execute(cmd)
            if len(rcode[1]) > 0: raise CmdError(rcode[1])
            return True
        except CmdError, e:
            print e
            sys.exit()
        except:
            print "### Unknown Error ###"
            print traceback.print_exc()
            sys.exit()
            
                
def process(answer):
    #iSCSI connection logic
    #Make iSCSI instance
    portal = None
    if answer.has_option("portal","ip"):
        portal = answer.get("portal","ip")
    else:
        while portal == None:
            ip_str = raw_input("Input iSCSI portal IP> ")
            if isIPaddr(ip_str):
                portal = ip_str
                break
            else:
                print "Invalid IP format"
    storage = iSCSI(portal)

    # find iSCSI session
    tf = storage.discovery()
    if tf == False:
        print "iSCSI target is not discovered"
        sys.exit()

    #############    
    # Login
    # iSCSI login
    #
    req_iqn = None
    my_hostname = socket.gethostname()
    if answer.has_option("iqn",my_hostname) == True:
        req_iqn = answer.get("iqn",my_hostname)
        
    # check 
    count = 0
    selected = False
    for item in storage.iqns:
        print "%s) %s %s" % (count,item[0],item[1])
        if req_iqn == item[1]:
            choice = count
            selected = True
        count = count + 1

    if selected == False:    
        choice = raw_input("select iqn #> ")
        
    (portal, target) = storage.iqns[int(choice)]
    storage.login(target,portal)

    print "================= Login IQN ======================="
    print storage.login_iqn

if __name__ == "__main__":
    parser = OptionParser()
    parser.add_option("-a","--answer", dest="answer", help="path to Answer file")

    (options, args) = parser.parse_args()
    if options.answer:
        answer = ConfigParser()
        if exists(options.answer):
            # Local file
            answer.readfp( open(options.answer) )
        else:
            # url
            fp = urllib.urlopen(options.answer)
            temp = open("/tmp/_iscsi_answer",'w')
            temp.write(fp.read())
            temp.close()
            answer.readfp( open("/tmp/_iscsi_answer") )
    else:
        answer = ConfigParser()

    process(answer)




